配合分支:day07/start,Repo: 按我
繼續驗證 App,比如說手動驗證的時候什麼都不輸入?真調皮,不過工程師就是這種變態的生物。常常想一些極端的 Edge cases。

結果立刻出事 😥。今天的功課是要避免上述的「空白」日記的發生。在進入開發之前,會進行使用者流程的確認 (畫成 Flow Chart 之類的),這類的空白情境應該要被考慮在裡頭。那修正該做在哪呢?
依然搬出資料流來判讀,不過這次我們站在使用者的角度來看,功能之間會怎麼流動。

從上述結果來看,有兩個可以動手腳的地方:
先避免兩者是空的就好,不過先不用檔其中一個沒填,避免一片空白的情形。今天我打算來從方案 2 進行調整,讀者可以自行實作看看方案 1。
接著用資料的角度來看,可以從哪邊攔截錯誤的資訊。

從資料流來看,最適合執行的地方,就是 onSave callback,也有兩種處理方式:
onSave 根本不會被搓到!onSave 發生後,只要出錯就不建立 newEntry。這次一樣是選第 2 條路。從這裡也可以知道,其實很多問題沒有什麼正確答案的修正方式,很多方法都可以達到效果,只是每種方法各有各的取捨(Tradeoff)。

我這裡就簡單粗暴的在 onSave callback 回去時檢查:只要 title 或是 note 是空的,就不理他了。
if 判斷式裡頭,變數加了驚嘆號,就會變成「不是」的意思,也可以寫成:title.isBlank() == false
if 判斷式裡頭的條件有 || 或,左邊右邊任何一個為真,就會執行。
&& 和,兩者都要成立,才會執行isBlank() 文件
雖然成功擋住了,但啥都不做的感覺不太好,使用者可能也會覺得哪裡怪怪的。所以為了提升使用者用起來的舒適度,來加上錯誤訊息提醒。
先在 DiaryForm 表格下面加一個錯誤訊息,如果有錯誤,才顯示:

輸入表格新增了一個新的欄位:validationError: String?,前幾天有說到 String 存的是文字。不過這裡怎麼多出一個 ?。這裡就需要引入一個觀念—— Null。
Null 代表「沒有東西」,這個變數沒有任何東西。如果一個變數後面「沒有 ?」則是保證「一定會有東西」,就像網購如果沒有被詐騙的話,裡面一定會有買的東西。但這個 ? 呢?貼在這個紙箱裡頭只代表「可能會有吧?」
用上面的 title 來說:
val title: String // 👈🏼 代表用的人,一定有 title 可以取出來
title.isBlank() // 👈🏼 打開瞧瞧是不是空白的,我不怕!因為保證一定有「文字」存在裡頭
但如果是薛丁格:
val title: String? // 👈🏼 用的人,不一定有 title 可以取出來,愛租已
title.isBlank() // 😨 不讓你這樣做,太刺激,裡頭可能「沒東西!」
程式碼會透過編譯器(Compiler),編譯(Compile) 成真正的 App,這樣操作 ? 的物件他會怕。那要怎麼樣讓他安心?就用 ?
val title: String? // 👈🏼 用的人,不一定有 title 可以取出來,愛租已
title?.isBlank() // 🤗 只有 title 不是「空」的,再去檢查就好!
用程式的術語來說 val title: String? 是一個 Nullable(可以是空) 的變數;val title: String 則是 Non-Null (不會是空) 的變數。
回到 DiaryForm 表格,所以我加了 validationError: String? 可以接受是空的,反正空的就不顯示就好了。再往下看到:

這又是什麼東西?這其實是檢查 validationError 如果不是空的,就執行 let 區塊的內容。而 errorMessage 是 Non-Null 的 validationError 可以直接拿來用,不用 ? 很方便吧。
這裡和任何的 Function Type 一樣,大括弧 {} 展開後取得的變數,不命名就是 it,本例重新命名為:errorMessage。 只要有 validationError 就做出錯誤的 Text。
接著往上看調整了什麼

新增了一個 String 變數,塞到 DiaryForm 裡頭,依據 callback function 做不同的變化。來看看最終效果如何:

看起來很讚!但⋯ 只要稍微旋轉一下手機,日記就不見了!這程式問題怎麼這麼多⋯⋯
!(不是):條件裡加驚嘆號會變成「不是」;也可以寫成 title.isBlank() == false。|| / &&:|| 是或、一邊為真就執行;&& 是和、兩邊都成立才執行。isBlank():Kotlin 用來判斷字串是不是空白;連只有空格的「 」也算空白。?:Null 代表沒有東西;String? 可能是空,沒有 ? 則保證一定有文字。?. 與 let:title?.isBlank() 只有不是空才檢查;validationError?.let 有值才顯示錯誤,it 可改名成 errorMessage。